import Cocoa

//var str = "Hello, playground"
//使用for in遍历字符串
//var item = "hello world"
//for c in item {
//    print("c is \(c)")
//}

//使用for in遍历数组
//var names = ["zhangsan", "lisi", "wangwu", "zhaoliu"]
//for name in names {
//    print("name is \(name)")
//}

//使用for in来遍历字典
//let dict = ["spider": 8, "ant": 6, "cat": 4]
//for item in dict {
//    print("\(item.key) has \(item.value) legs")
//}

//另一种写法,直接给字典的key,value取个名字
//let dict = ["spider": 8, "ant": 6, "cat": 4]
//for (animalName, legsCount) in dict {
//    print("\(animalName) has \(legsCount) legs")
//}

//另一种写法:直接取下标
//let dict = ["spider": 8, "ant": 6, "cat": 4]
//for t in dict {
//    print("\(t.0) has \(t.1) legs")
//}

//获取3的5次方
//let base = 3
//let power = 5
//var result: Int = 1
////for i in 1...power {
////    result *= base
////}
////因为这里只是要取3的5次方的值,只是单纯的遍历5次,可以不需要序列的每一个值,所以可以去掉序列值使用"_"来忽略这个序列值
//for _ in 1...5 {
//    result *= base
//}
//print(result)


//使用for in分段区间 :stride(from: 0, to: 50, by: minuteInterval):半开半闭区间
//let minuteInterval = 5
//tick mark:刻度线
//从0开始,每5个刻度循环一次,一直循环到50,因为是半开半闭区间,所以取不到50,打印只能到45
//stride:跨越,跨过,大步走
//for tickMark in stride(from: 0, to: 50, by: minuteInterval) {
//    print(tickMark)
//}

//从0开始,每5个刻度循环一次,一直循环到50,因为是闭区间,所以可以取到50,打印到50
//for tickMark in stride(from: 0, through: 50, by: minuteInterval) {
//    print(tickMark)
//}

//repeat-while循环,和OC的do-while循环是一样的
//var count = 0
//repeat {
//    print(count)
//    count += 1
//}while count < 5  //一旦while里面的条件不满足时则立即停止循环


/**
 1. oc中的switch只能判断整数
 2. oc中的switch可以穿透,可以连着写两个case条件但是不加break
 3. oc中的switch必须要带上break,表示跳出条件语句
 4. 在case中不带上大括号创建变量,程序会报错,因为不加大括号,这个变量的值会穿透整个语句
 5. oc中可以不写default
 6. oc中的default位置可以随便放
 */
//int number = 10;
//switch (number) {
//default:
//    NSLog(@"差");
//    break;
//case 9:    //oc中的switch可以穿透,可以连着写两个case条件但是不加break
//case 10:{
//    NSString *name = @"老王";
//    NSLog(@"%@ 好",name);
//    break;
//    }
//case 8:
//    NSLog(@"一般");
//    //        default:
//    //            NSLog(@"差");
//    //            break;
//}


/**
 swift的swich相比于OC更加的强大
 1. 不需要break,只要符合其中一个case的条件语句,就会跳出swich
 2. OC必须是整数(int)类型,Swift中可以是对象,也可以duoble类型(可以对任意数据类型进行检测)
 3. 不能没有default,default位置只能在最后
 4. 各个cese之间不能穿透,如果有多个值,可以使用","隔开
 5. 定义变量不需要使用{}分隔作用域
 6. 在Swift中,必须涵盖所有条件,每个case至少包含一条语句
 7. swich也可以使用区间运算
 8. swich也可以用在元组里面
 9. 值绑定(swich的case可以将匹配到的值绑定为一个临时的常量或者变量,来给case函数体使用)
 10. 可以使用where分句来检查是否符合特定的约束(根据条件绑定)
*/
//let number = "10"  //可以定义任意数据类型
//switch number {
//case "10", "9":   //注意OC是不能这样写的(各个cese之间不能穿透,如果有多个值,可以使用","隔开)
//    print("优")
//case "8":
//    let name = "老王"   //这里定义变量可以不用大括号进行分隔
//    print("\(name)一般")
//default:
//    print("差")
//}



////swich也可以使用区间运算
//let number = 62
//switch number {
//case 1..<12:
//    print("这个数的范围是1到12")
//case 12..<100:
//    print("这个数的范围是12到100")
//case 100..<1000:
//    print("这个数的范围是100到1000")
//default:
//    print("many")
//}


//swich也可以用在元组里面,元组和区间并用
//let somePoint = (1, 1)
//switch somePoint {
//case (0, 0):
//    print("the point at the origin")
//case (1, 0):
//    print("(\(somePoint.0), 0) is on the x-axis")
//case (0, 1):
//    print("(0, \(somePoint.1)) is on the y-axis")
//case (-2...2, -2...2):   //可以在元组中间再加上区间
//    print("(\(somePoint.0), \(somePoint.1)) is inside the box")
//default:
//    print("(\(somePoint.0), \(somePoint.1)) is outside the box")
//}

////"_"表明匹配所有可能的值   "_":通配符
//let somePoint = (1, 1)
//switch somePoint {
//case (0, 0):
//    print("the point at the origin")
//case (_, 0):
//    print("somePoint is on the x-axis")
//case (0, _):
//    print("somePoint is on the y-axis")
//case (-2...2, -2...2):
//    print("somePoint is inside the box")
//default:
//    print("somePoint is outside the point")
//}

////值绑定(swich的case可以将匹配到的值绑定为一个临时的常量或者变量,来给case函数体使用)
//let somePoint = (1, 1)
//switch somePoint {
//case (0, 0):
//    print("the point at the origin")
//case (let x, 0):  //会将somePoint中X的值赋值给X
//    print("(\(somePoint.0), \(somePoint.1)) is on the x-axis, it is value is \(x)")
//case (0, let y):
//    print("on the y-axis with a value is \(y)")
//case (let x, let y):  // 会将point中XY的值赋值给XY
//    print("someWhere else at (\(x), \(y)) ")
////default:   //如果前面已经有匹配case的值了,没有省略default的话,这里会报一个警告(Default will never be executed,表示这个语句永远不会被执行)所以这里的default可以省略
////    print("somePoint is outside the point")
//}

//swich case可以使用where分句来检查是否符合特定的约束(根据条件绑定)
//let anotherPoint = (1, -1)
//switch (anotherPoint) {
//case let (x, y) where x == y:
//    print("(\(x), \(y)) is on the line x == y")
//case let (x, y) where x == -y:  //只有where后面的条件表达式为真才赋值并执行case后的语句
//    print("(\(x), \(y)) is on the line x == -y")
//case let (x, y):
//    print("(\(x), \(y)) is other point")
//}

////复合匹配
//let someCharacter: Character = "e"
//switch someCharacter {
//case "a", "o", "e", "i", "u":
//    print("\(someCharacter) is a vowel") //vowel:元音
//case "b", "c", "d", "f", "g", "h":
//    print("\(someCharacter) is a consonant") //consonant:辅音
//default:
//    print("\(someCharacter) is not a vowel or a consonant")
//}


////复合值绑定
//let anotherPoint = (9, 0)
//switch anotherPoint {
//case (let distence, 0), (0, let distence):    //元组加上值绑定,有多个值,使用了","隔开
//    print("\(distence) from the origin")
//default:
//    print("no no no")
//}

//swich的流程控制符转移
//continue告诉循环停止正在做的事情并且再次从头开始循环的下一次遍历,他是说"我不再继续当前的循环遍历了"而不是离开整个当前循环
//let someCharacter: Character = "a"
//switch someCharacter {
//case "A":
//    print("这个字母是大写的A")
//case "a":
//    print("is the first letter of the alphabet")
//   // break  //可以不添加break,只要符合其中一个case的条件语句,就会跳出swich
//case "z":
//    print("the last letter of the alphabet")
//    break
//default:
//    print("no one letter")
//    break
//}

////fallthrough:如果需要C或者OC一样风格的贯穿行为,可以使用fallthrogh,只要使用了fallthrogh,不会立即跳出switch语句,后面的case条件语句一样会执行
//let someCharacter: Character = "a"
//switch someCharacter {
//case "A":
//    print("这个字母是大写的A")
//    fallthrough
//case "a":
//    print("is the first letter of the alphabet")
//    fallthrough
//case "z":
//    print("the last letter of the alphabet")
//    fallthrough
//default:
//    print("no one letter")
//}
//
////输出结果:  is the first letter of the alphabet
////          the last letter of the alphabet
////          no one letter


//语句标签:可以用语句标签来给循环语句或者条件语句做标记.
var number = 10
whileLoop: while number > 0 {
    switch number {
    case 9:
        print("9")
    case 10:
        var sum = 0
        for index in 1...10 {
            sum += index
            if index == 9 {
                print(sum)
                break whileLoop
            }
        }
    default:
        break
    }
    number -= 1
}

//let oName: String?
//oName = "老李"
//if oName != nil {
//    print(oName! + "好")
//}
//
////合并空值运算符"??", 如果 ?? 前面的值为nil,则使用 ?? 后面的值
//print((oName! ?? "老王") + "也好")
////由此可见 + 运算符优先级低于 ?? 合并空值运算符
//print(oName! ?? "老王" + "也好")


//guard黄金,大道原则,相比于if没有那么多层的嵌套,不会把他的核心业务代码都放到if条件语句的嵌套里面,代码的可读性高
//首先使用if条件语句看看   split:分离,分解.离开
//func isIpAddress(IpAddr: String) -> (Int, String) {
//    let components = IpAddr.split(separator: ".")
//    if components.count == 4 {
//        if let first = Int(components[0]), first >= 0 && first < 256 {
//            if let second = Int(components[1]), second >= 0 && second < 256 {
//                if let third = Int(components[2]), third >= 0 && third < 256 {
//                    if let fourth = Int(components[3]), fourth >= 0 && fourth < 256 {
//                       return (0, "Ip地址正确")
//                    } else {
//                        return (4, "第四个数不对")
//                    }
//                } else {
//                    return (3, "第三个数不对")
//                }
//            } else {
//                return (2, "第二个数不对")
//            }
//        } else {
//            return (1, "第一个数不对")
//        }
//    } else {
//        return (100, "Ip只有4部分")
//    }
//}
//print(isIpAddress(IpAddr: "1271.0.0.1"))


//使用guard看看
func isIpAddress(iPaddr: String) -> (Int, String) {
    let components = iPaddr.split(separator: ".")
    guard components.count  == 4 else {
        return (100, "IP地址只有4部分")
    }
    guard let first = Int(components[0]), first >= 0 && first < 256 else {
        return (1, "第一个数不对")
    }
    guard let second = Int(components[1]), second >= 0 && second < 256 else {
        return (2, "第二个数不对")
    }
    guard let third = Int(components[2]), third >= 0 && third < 256 else {
        return (3, "第三个数不对")
    }
    guard let fourth = Int(components[3]), fourth >= 0 && fourth < 256 else {
        return (4, "第四个数不对")
    }
    return (0, "IP地址正确")
}

print(isIpAddress(iPaddr: "127.0.0.1"))

func demo() {
    let oName: String? = "张三"
    let oAge: Int? = 20
    guard let name = oName else {
        print("name 为nil")
        return
    }
    guard let age = oAge else {
        print("age 为nil")
        return
    }
    //执行到此,name和age一定有值
    //在实际开发中,复杂的代码在条件判断之后
    //使用guard会让嵌套层次少一层
    print("Hi \(name) --- \(age)")
}

